﻿''' <summary>
''' 所属している全グループ画面のフォームです。
''' </summary>
''' <remarks></remarks>
Friend NotInheritable Class InRoleGroupList

#Region " プライベートフィールド "
  Private ReadOnly member As DomainObject   'メンバー
  Private ReadOnly allGroups As Dictionary(Of String, DomainGroup)  '全グループ(Key:distinguishedName)
  Private ReadOnly addedDisplayNames As List(Of String)   'リストに追加したグループの表示テキスト
#End Region

#Region " パブリックコンストラクター "
  ''' <summary>
  ''' メンバーを指定して InRoleGroupList クラスの新しいインスタンスを初期化します。
  ''' </summary>
  ''' <param name="member">メンバー。</param>
  ''' <remarks></remarks>
  Public Sub New(member As DomainObject)
    ' この呼び出しはデザイナーで必要です。
    InitializeComponent()
    ' InitializeComponent() 呼び出しの後で初期化を追加します。

    Me.member = member
    allGroups = DirectoryAccess.GetGroups(Of DomainGroup)().ToDictionary(
      Function(group) group.Entry.Properties.Item("distinguishedName").Value.ToString(), Function(group) group)
    addedDisplayNames = New List(Of String)()

    Me.AddChildNode()   '子ノードを追加
    Me.GroupListBox.DataSource = addedDisplayNames
    Me.ViewPanel.Enabled = addedDisplayNames.Count > 1
    Me.GroupTreeView.ExpandAll()
  End Sub
#End Region

#Region " イベントハンドラ "
  Private Sub RadioButton_CheckedChanged(
    sender As Object, e As EventArgs) Handles TreeRadioButton.CheckedChanged, ListRadioButton.CheckedChanged

    Me.GroupTreeView.Visible = sender Is Me.TreeRadioButton
    Me.GroupListBox.Visible = Not Me.GroupTreeView.Visible
  End Sub
#End Region

#Region " プライベートメソッド "
  ''' <summary>
  ''' 子ノードを追加します。
  ''' </summary>
  ''' <remarks></remarks>
  Private Sub AddChildNode()
    Dim node As New TreeNode(member.ToString(), member.Category, member.Category)
    Me.GroupTreeView.Nodes.Add(node)
    If (member.Category = CategoryType.User) OrElse (member.Category = CategoryType.Computer) Then
      'プライマリー グループを追加
      Dim primaryGroupId = If(member.Category = CategoryType.User,
        DirectCast(member, DomainUser).PrimaryGroupId, DirectCast(member, Computer).PrimaryGroupId)
      Dim group = allGroups.Values.Cast(Of DomainGroup)().Single(Function(grp) grp.Token = primaryGroupId)
      Me.AddChildNode(node, group)  '子ノードを追加
    End If
    '所属するグループを追加
    For Each memberOf As String In member.Entry.Properties.Item("memberOf")
      Me.AddChildNode(node, allGroups.Item(memberOf))   '子ノードを追加
    Next
  End Sub

  ''' <summary>
  ''' 子ノードを追加します。
  ''' </summary>
  ''' <param name="node">子ノードを追加するノード。</param>
  ''' <param name="group">子ノードになるグループ。</param>
  ''' <remarks></remarks>
  Private Sub AddChildNode(node As TreeNode, group As DomainGroup)
    Dim childNode = CreateNode(group)   'ノードを作成
    node.Nodes.Add(childNode)
    If addedDisplayNames.Contains(childNode.Text) = False Then
      addedDisplayNames.Add(childNode.Text)   '表示するテキストを追加
    End If
    'ネストしているグループを追加
    For Each memberOf As String In group.Entry.Properties.Item("memberOf")
      Me.AddChildNode(childNode, allGroups.Item(memberOf))  '子ノードを追加
    Next
  End Sub

  ''' <summary>
  ''' 指定したグループのノードを作成します。
  ''' </summary>
  ''' <param name="group">グループ。</param>
  ''' <returns>作成したノード。</returns>
  ''' <remarks></remarks>
  Private Function CreateNode(group As DomainGroup) As TreeNode
    Dim displayName = String.Format("{0}（{1}）", group.Name, group.Scope)  '表示するテキスト
    Dim fontColor As Color
    Select Case group.ScopeType
      Case DomainGroupScopeType.DomainLocal
        fontColor = Color.Blue
      Case DomainGroupScopeType.Global
        fontColor = Color.Green
      Case DomainGroupScopeType.Universal
        fontColor = Color.Brown
    End Select

    Return New TreeNode(displayName) With {.Name = group.Name, .ForeColor = fontColor}
  End Function
#End Region
End Class